using AutoMapper;
using MediatR;
using S.M.SmartMedical.API.Read.Application.Query;
using S.M.SmartMedical.Domain.DTOs;
using S.M.SmartMedical.Domain.Entities;
using S.M.SmartMedical.Domain.Enums;
using S.M.SmartMedical.ErrorCode;
using S.M.SmartMedical.Infrastructure.BaseRepository;
using System.Security.Cryptography;
using System.Text;

namespace S.M.SmartMedical.API.Read.Application.Handler
{
    /// <summary>
    /// 用户登录查询处理器
    /// </summary>
    public class LoginUserHandler : IRequestHandler<LoginUserQuery, APIResult<UserInfoDto>>
    {
        private readonly IRepository<User> _userRepository;
        private readonly IMapper _mapper;
        private readonly ILogger<LoginUserHandler> _logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="userRepository">用户仓储</param>
        /// <param name="mapper">对象映射器</param>
        /// <param name="logger">日志记录器</param>
        public LoginUserHandler(
            IRepository<User> userRepository,
            IMapper mapper,
            ILogger<LoginUserHandler> logger)
        {
            _userRepository = userRepository;
            _mapper = mapper;
            _logger = logger;
        }

        /// <summary>
        /// 处理用户登录查询
        /// </summary>
        /// <param name="request">登录查询</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>登录结果</returns>
        public async Task<APIResult<UserInfoDto>> Handle(LoginUserQuery request, CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogInformation("开始处理用户登录，用户名：{UserName}", request.UserLogin.UserName);

                // 根据用户名查找用户
                var user = await _userRepository.GetAsync(u => u.UserName == request.UserLogin.UserName);
                if (user == null)
                {
                    _logger.LogWarning("用户不存在：{UserName}", request.UserLogin.UserName);
                    return new APIResult<UserInfoDto>
                    {
                        Code = APIEnum.Fail,
                        Message = "用户名或密码错误",
                        Data = null!
                    };
                }

                // 验证密码
                var hashedPassword = HashPassword(request.UserLogin.Password);
                if (user.Password != hashedPassword)
                {
                    _logger.LogWarning("密码错误，用户名：{UserName}", request.UserLogin.UserName);
                    return new APIResult<UserInfoDto>
                    {
                        Code = APIEnum.Fail,
                        Message = "用户名或密码错误",
                        Data = null!
                    };
                }

                // 检查用户状态
                if (user.Status != UserStatus.Normal)
                {
                    string statusMessage = user.Status switch
                    {
                        UserStatus.Disabled => "账户已被禁用",
                        UserStatus.Locked => "账户已被锁定",
                        _ => "账户状态异常"
                    };

                    _logger.LogWarning("用户状态异常，用户名：{UserName}，状态：{Status}", request.UserLogin.UserName, user.Status);
                    return new APIResult<UserInfoDto>
                    {
                        Code = APIEnum.Fail,
                        Message = statusMessage,
                        Data = null!
                    };
                }

                // 更新最后登录时间
                user.LastLoginTime = DateTime.Now;
                user.UpdateTime = DateTime.Now;
                user.UpdateUserName = user.UserName;
                await _userRepository.UpdateAsync(user);

                _logger.LogInformation("用户登录成功，用户名：{UserName}，用户ID：{UserId}", user.UserName, user.Id);

                // 映射返回数据
                var userInfo = _mapper.Map<UserInfoDto>(user);
                return new APIResult<UserInfoDto>
                {
                    Code = APIEnum.OK,
                    Message = "登录成功",
                    Data = userInfo
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "用户登录过程中发生异常，用户名：{UserName}", request.UserLogin.UserName);
                return new APIResult<UserInfoDto>
                {
                    Code = APIEnum.Fail,
                    Message = "登录失败，系统异常",
                    Data = null!
                };
            }
        }

        /// <summary>
        /// 密码哈希加密
        /// </summary>
        /// <param name="password">原始密码</param>
        /// <returns>加密后的密码</returns>
        private static string HashPassword(string password)
        {
            using var sha256 = SHA256.Create();
            var hashedBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(password));
            return Convert.ToBase64String(hashedBytes);
        }
    }
}